package me.yricky.mayu.utils

/**
 * @author Yricky
 * @date 2022/4/17
 */

fun String.asList():StringBasedCharList{
    return object :StringBasedCharList,List<Char> by list(length,{get(it)}) {
        override val string: String = this@asList
    }
}

fun CharSequence.asList():CharSequenceBasedCharList{
    return object :CharSequenceBasedCharList,List<Char> by list(length,{get(it)}){
        override val charSequence: CharSequence = this@asList
    }
}

interface StringBasedCharList:CharSequenceBasedCharList{
    val string:String
    override val charSequence: CharSequence get() = string
}

interface CharSequenceBasedCharList:List<Char>{
    val charSequence:CharSequence
}

fun List<Char>.string():String{
    return if(this is StringBasedCharList){
        string
    }else{
        val sb = StringBuilder()
        forEach {
            sb.append(it)
        }
        sb.toString()
    }
}


fun <T> list(length: Int, getter:(Int)->T):List<T> = object :BaseListImpl<T>{
    override val size: Int = length
    override fun get(index: Int): T =getter(index)
}

interface BaseListImpl<T>:List<T>{

    override fun contains(element: T): Boolean = !all { it != element }

    override fun containsAll(elements: Collection<T>): Boolean =elements.all { contains(it) }

    override fun indexOf(element: T): Int = indexOfFirst { it == element }

    override fun isEmpty(): Boolean = size == 0

    override fun iterator(): Iterator<T> = listIterator()

    override fun lastIndexOf(element: T): Int = indexOfLast { it == element }

    override fun listIterator(): ListIterator<T> =listIterator(0)

    override fun listIterator(index: Int): ListIterator<T> {
        return object :ListIterator<T>{
            private var nextIndex = index.coerceIn(0,size)
            override fun hasNext(): Boolean = nextIndex < size
            override fun next(): T = get(nextIndex++)
            override fun hasPrevious(): Boolean = nextIndex > 0
            override fun nextIndex(): Int = nextIndex
            override fun previous(): T = get(--nextIndex)
            override fun previousIndex(): Int = nextIndex - 1
        }
    }

    override fun subList(fromIndex: Int, toIndex: Int): List<T> = list((toIndex-fromIndex).coerceAtLeast(0)){
        get(it + fromIndex)
    }
}



